#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
#include <linux/kernel_stat.h>
#include <asm/uaccess.h>
#include <asm/cputime.h>
#include <linux/tracepoint.h>

#define MODULE_NAME "trace_schedule"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Steven Hofmeyr (LBNL)");
MODULE_DESCRIPTION("Traces schedule calls");

// pretty colors for output           
#define _RED_ "\x1b[31m"
#define _GREEN_ "\x1b[32m"
#define _BROWN_ "\x1B[33m"
#define _BLUE_ "\x1b[34m"
#define _MAGENTA_ "\x1b[35m"
#define _CYAN_ "\x1b[36m"
#define _LIGHTGRAY_ "\x1B[37m"
#define _DARKGRAY_ "\x1B[1m\x1B[0m"
#define _LIGHTRED_ "\x1B[1m\x1B[31m"
#define _LIGHTGREEN_ "\x1B[1m\x1B[32m"
#define _YELLOW_ "\x1B[1m\x1B[33m"
#define _LIGHTBLUE_ "\x1B[1m\x1B[34m"
#define _LIGHTMAGENTA_ "\x1B[1m\x1B[35m"
#define _LIGHTCYAN_ "\x1B[1m\x1B[36m"
#define _END_ "\x1b[0m"

#define PRINTCON(fmt, ...) \
  do {                                            \
    char buf[1000];                               \
    snprintf(buf, 1000, fmt, __VA_ARGS__);        \
    printcon(buf);                                \
  } while(0);

static void printcon(char *str) {
  struct tty_struct *my_tty = current->signal->tty;
  if (my_tty != NULL) {
    ((my_tty->driver->ops)->write) (my_tty, str, strlen(str));
    ((my_tty->driver->ops)->write) (my_tty, "\015\012", 2);
  }
}

static int __init init_trace_schedule(void) {
  PRINTCON(_BLUE_ "%s loaded" _END_, MODULE_NAME);
  return 0;
}

static void __exit cleanup_trace_schedule(void) {
  PRINTCON(_BLUE_ "%s unloaded" _END_, MODULE_NAME);
}

module_init(init_trace_schedule);
module_exit(cleanup_trace_schedule);

